package com.nononsenseapps.feeder.ui.category

import android.view.ViewGroup
import androidx.paging.CombinedLoadStates
import androidx.paging.PagingData
import androidx.recyclerview.widget.RecyclerView
import com.nononsenseapps.feeder.db.view.PreviewItem
import com.nononsenseapps.feeder.ui.feed.FeedItemPagedListAdapter
import com.nononsenseapps.feeder.util.FeedViewListType


class CompAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder>(){

    val adapterMap= mutableMapOf<String,RecyclerView.Adapter<RecyclerView.ViewHolder>>()

    var adapter:RecyclerView.Adapter<RecyclerView.ViewHolder>?=null

    var loadStateListener: ((CombinedLoadStates) -> Unit)? = null


    private val adapterObserver=object:RecyclerView.AdapterDataObserver(){
        override fun onChanged() {
           notifyDataSetChanged()
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
            notifyItemRangeChanged(positionStart, itemCount)
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
            notifyItemRangeChanged(positionStart, itemCount, payload)
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            notifyItemInserted(positionStart)
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            notifyItemRangeRemoved(positionStart, itemCount)
        }

        override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
            notifyItemMoved(fromPosition, toPosition)
        }

        override fun onStateRestorationPolicyChanged() {

        }
    }


    fun put(key:String,adapter:RecyclerView.Adapter<RecyclerView.ViewHolder>,default:Boolean=false){
        adapterMap[key]=adapter
        if(default)
           changeAdapter(key,null)
    }

    fun changeAdapter(key: String,treeName: String?){
        val current = adapterMap[key]?:return

        if(current == adapter) {
            if(adapter is FeedItemTagTreeAdapter) {
                treeName?.let {
                    changeTreeName(it)
                }
            }
            return
        }

        if(adapter!=null)
           beforeChangeAdapterListener()

        adapter = current
        afterChangeAdapterListener()

        if(adapter is FeedItemTagTreeAdapter) {
            treeName?.let {
                changeTreeName(it)
            }
        }

        notifyDataSetChanged()
    }

    fun changeTreeName(treeName:String){
        ( requestAdapter() as FeedItemTagTreeAdapter).changeTagTreeType(treeName)
    }

    private fun requestAdapter():RecyclerView.Adapter<RecyclerView.ViewHolder>{
        if(adapter==null) throw IndexOutOfBoundsException()
        return adapter!!
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return requestAdapter().onCreateViewHolder(parent, viewType)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        requestAdapter().onBindViewHolder(holder, position)
    }

    override fun getItemCount(): Int {
        return requestAdapter().itemCount
    }

    override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        requestAdapter().onBindViewHolder(holder, position, payloads)
    }

    override fun findRelativeAdapterPositionIn(
        adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>,
        viewHolder: RecyclerView.ViewHolder,
        localPosition: Int
    ): Int {
        return requestAdapter().findRelativeAdapterPositionIn(adapter, viewHolder, localPosition)
    }

    override fun getItemViewType(position: Int): Int {
        return requestAdapter().getItemViewType(position)
    }

    override fun setHasStableIds(hasStableIds: Boolean) {
        requestAdapter().setHasStableIds(hasStableIds)
    }

    override fun getItemId(position: Int): Long {
        return requestAdapter().getItemId(position)
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        requestAdapter().onViewRecycled(holder)
    }

    override fun onFailedToRecycleView(holder: RecyclerView.ViewHolder): Boolean {
        return requestAdapter().onFailedToRecycleView(holder)
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        requestAdapter().onViewAttachedToWindow(holder)
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        requestAdapter().onViewDetachedFromWindow(holder)
    }


    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        requestAdapter().onDetachedFromRecyclerView(recyclerView)
    }

    suspend  fun  submitData(pagingData: PagingData<PreviewItem>) {
        val adapter=requestAdapter()
        if(adapter is FeedItemPagedListAdapter)
           adapter.submitData(pagingData)
    }

    suspend  fun submitData(pagingData: List<PreviewItem>) {
        val adapter=requestAdapter()
        if(adapter is FeedItemTagTreeAdapter)
            adapter.submitData(pagingData)
    }

    fun getCurrentItemList(): List<PreviewItem> {
        val adapter=requestAdapter()
        if(adapter is FeedItemPagedListAdapter)
           return adapter .getCurrentItemList()
        return emptyList()
    }

    fun getAboveItemList(item: PreviewItem): List<PreviewItem>?  {
        val adapter=requestAdapter()
        if(adapter is FeedItemPagedListAdapter)
            return adapter.getAboveItemList(item)
        return emptyList()
    }

    fun getBelowItemList(item: PreviewItem): List<PreviewItem>? {
        val adapter=requestAdapter()
        if(adapter is FeedItemPagedListAdapter)
            return adapter .getBelowItemList(item)
        return emptyList()
    }

    fun addLoadStateListener(listener: (CombinedLoadStates) -> Unit) {
        this.loadStateListener = listener
        if(adapter!=null)
            addAdapterListener()
    }

    fun removeLoadStateListener(){
        if(adapter != null)
            removeAdapterListener()
        this.loadStateListener = null
    }

    private fun beforeChangeAdapterListener(){
        val adapter=requestAdapter()
        adapter.unregisterAdapterDataObserver(adapterObserver)
        removeAdapterListener()
    }

    private fun afterChangeAdapterListener(){
        val adapter=requestAdapter()
        adapter.registerAdapterDataObserver(adapterObserver)
        addAdapterListener()
    }

    private fun removeAdapterListener(){
        val adapter=requestAdapter()
        if(adapter is FeedItemPagedListAdapter){
            if(loadStateListener != null)
                adapter.removeLoadStateListener(loadStateListener!!)
        }
    }

    private fun addAdapterListener() {
        val adapter = requestAdapter()
        if(adapter is FeedItemPagedListAdapter){
            if(loadStateListener != null )
                adapter.addLoadStateListener(loadStateListener!!)
        }
    }

    fun setFeedViewListType(feedViewListType: FeedViewListType,treeName:String?) {
        val adapter = requestAdapter()
        if(adapter is FeedItemPagedListAdapter){
            if(feedViewListType!=FeedViewListType.TREE) {
                if (loadStateListener != null)
                    adapter.setFeedViewListType(feedViewListType)
            }else {
                changeAdapter(ADAPTER_TYPE_TREE, treeName)
            }
        }else if(feedViewListType!=FeedViewListType.TREE) {
            changeAdapter(ADAPTER_TYPE_LIST,treeName)
            setFeedViewListType(feedViewListType,treeName)
        }
    }

    fun setReverseListOrder(it: Boolean) {

    }



    companion object{
        const val ADAPTER_TYPE_LIST="list"
        const val ADAPTER_TYPE_TREE="tree"
    }
}
